#include<fstream>
#include<string>
#include<vector>
#include<map>
#include"string_conversation.h"
#include"get_editor_script.h"
#include"list_of_constants.h"

std::vector<std::string> getTextFromInput(const char* path){
	std::ifstream input(path);
	std::vector<std::string> listOfStrings;
	std::string inputString;
	while (getline(input, inputString)){
		listOfStrings.push_back(inputString);
	}
	input.close();
	return listOfStrings;
}

void getHashesFromInput(const std::vector<std::string>& listFromInput,
	std::map<std::string, long long>& keys,
	std::vector<long long>& hashes
	){
	long long currentHash = keys.size();
	for (const auto& currentString: listFromInput){
		if (keys.find(currentString) != keys.end())
			hashes.push_back(keys[currentString]);
		else{
			keys[currentString] = currentHash;
			hashes.push_back(currentHash);
			++currentHash;
		}
	}
	
}

void countReverseKeys(std::vector<std::string> &keysReverse, const std::map<std::string, long long> & keys){
	if (keysReverse.empty()){
		keysReverse.resize(keys.size());
	}
	for (const auto& currentString : keys){
		keysReverse[currentString.second] = currentString.first;
	}
	
}

void outputEditorChanges(const char* path,
	const std::vector<std::string>& keysReverse,
	const std::vector< EditorState<long long> >& editorScript
	){
	std::ofstream output(path);
	
	for (size_t i = 0; i < editorScript.size(); ++i){
		output << editorScript[i].signOfState << keysReverse[editorScript[i].stringOfState] << std::endl;
	}
	output.close();
}

std::vector<EditorState<std::string> >  gettingChangesOfTwoFiles(
	std::vector<std::string>& listFromFirstInput,
	std::vector<std::string>& listFromSecondInput,
	const char* inputPath1, const char* inputPath2, const char* outputPath,
	int mode){
	listFromFirstInput = getTextFromInput(inputPath1);
	listFromSecondInput = getTextFromInput(inputPath2);

	std::map<std::string, long long> keys;
	std::vector<std::string> keysReverse;
	std::vector<long long> hashes1;
	std::vector<long long> hashes2;
	getHashesFromInput(listFromFirstInput, keys, hashes1);
	getHashesFromInput(listFromSecondInput, keys, hashes2);
	countReverseKeys(keysReverse, keys);
	
	PackOfIterators<std::vector<long long>::iterator> boundsOfContainers(
		hashes1.begin(), hashes1.end(),hashes2.begin(), hashes2.end());
	
	std::vector<EditorState<long long> > editorScript = getEditorScript(boundsOfContainers);
	
	outputEditorChanges(outputPath, keysReverse, editorScript);
	std::vector<EditorState<std::string> > stringResult;
	if (mode == 0){
		for (size_t i = 0; i < editorScript.size(); ++i){
			stringResult.push_back(EditorState<std::string>(editorScript[i].signOfState,
				keysReverse[editorScript[i].stringOfState]));
		}
	}
	return stringResult;
}
